home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / mg2a_src.zip / SYS / VMS / TTYIO.C < prev    next >
C/C++ Source or Header  |  1988-08-23  |  8KB  |  291 lines

  1. /*
  2.  * Name:    MicroGnuEmacs
  3.  *        VAX/VMS terminal I/O.
  4.  *        o 16-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  5.  *          Turn off TTSYNC so ^S and ^Q are sent to program.
  6.  *          To get this back, compile with -DFLOWCONTROL
  7.  *        o 10-Jul-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  8.  *          Add setttysize(), typeahead() and panic() for Gnu v30
  9.  *        o 21-Jul-87 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  10.  *          Use transmit speed from iosb instead of receive, which
  11.  *          is only valid if different from the transmit speed...
  12.  */
  13. #include    "def.h"
  14.  
  15. #include    <stsdef.h>
  16. #include    <ssdef.h>
  17. #include    <descrip.h>
  18. #include    <iodef.h>
  19. #include    <ttdef.h>
  20. #include    <tt2def.h>
  21.  
  22. #define    NIBUF    128            /* Probably excessive.        */
  23. #define    NOBUF    512            /* Not too big for 750/730.    */
  24. #define    EFN    0            /* Event flag            */
  25.  
  26. char    obuf[NOBUF];            /* Output buffer        */
  27. int    nobuf;                /* # of bytes in above        */
  28. char    ibuf[NIBUF];            /* Input buffer            */
  29. int    nibuf;                /* # of bytes in above        */
  30. int    ibufi;                /* Read index            */
  31. int    oldmode[3];            /* Old TTY mode bits        */
  32. int    newmode[3];            /* New TTY mode bits        */
  33. short    iochan;                /* TTY I/O channel        */
  34. int    nrow;                /* Terminal size, rows.        */
  35. int    ncol;                /* Terminal size, columns.    */
  36. short    ospeed;                /* Terminal output speed    */
  37.                     /* for termcap library        */
  38.  
  39. /*
  40.  * This routines gets called once, to set up the
  41.  * terminal channel.
  42.  * On VMS we find the translation of the SYS$COMMAND:
  43.  * logical name, assign a channel to it, and set it raw.
  44.  */
  45.  
  46. ttopen()
  47. {
  48.     struct    dsc$descriptor    idsc;
  49.     struct    dsc$descriptor    odsc;
  50.     char    oname[40];
  51.     int    iosb[2];
  52.     int    status;
  53.  
  54.     odsc.dsc$a_pointer = "SYS$COMMAND";
  55.     odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
  56.     odsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  57.     odsc.dsc$b_class   = DSC$K_CLASS_S;
  58.     idsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  59.     idsc.dsc$b_class   = DSC$K_CLASS_S;
  60.     do {
  61.         idsc.dsc$a_pointer = odsc.dsc$a_pointer;
  62.         idsc.dsc$w_length  = odsc.dsc$w_length;
  63.         odsc.dsc$a_pointer = &oname[0];
  64.         odsc.dsc$w_length  = sizeof(oname);
  65.         status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
  66.         if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
  67.             exit(status);
  68.         if (oname[0] == 0x1B) {
  69.             odsc.dsc$a_pointer += 4;
  70.             odsc.dsc$w_length  -= 4;
  71.         }
  72.     } while (status == SS$_NORMAL);
  73.     status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
  74.     if (status != SS$_NORMAL)
  75.         exit(status);
  76.     status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
  77.               oldmode, sizeof(oldmode), 0, 0, 0, 0);
  78.     if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  79.         exit(status);
  80.  
  81.     nrow = (oldmode[1]>>24) & 0xFF;        /* Terminal length.    */
  82.     if (nrow > NROW)
  83.         nrow = NROW;
  84.     ncol = (oldmode[0]>>16) & 0xFFFF;    /* Width.        */
  85.     if (ncol > NCOL)
  86.         ncol = NCOL;
  87.     ospeed = (iosb[0]>>16) & 0xFF;        /* Speed (for termcap)    */
  88.     newmode[0] = oldmode[0];        /* Only in version 4.    */
  89. #ifdef    FLOWCONTROL
  90.     newmode[1] = oldmode[1] | TT$M_NOECHO | TT$M_TTSYNC;
  91. #else
  92.     newmode[1] = (oldmode[1] | TT$M_NOECHO) & ~TT$M_TTSYNC;
  93. #endif
  94.     newmode[2] = oldmode[2] | TT2$M_PASTHRU;
  95.     status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  96.               newmode, sizeof(newmode), 0, 0, 0, 0);
  97.  
  98.     if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  99.         exit(status);
  100. }
  101.  
  102. /*
  103.  * This function gets called just
  104.  * before we go back home to the command interpreter.
  105.  * On VMS it puts the terminal back in a reasonable state.
  106.  */
  107. ttclose()
  108. {
  109.     int    status;
  110.     int    iosb[2];
  111.  
  112.     ttflush();
  113.     status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  114.              oldmode, sizeof(oldmode), 0, 0, 0, 0);
  115.     if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  116.         exit(status);
  117.     status = SYS$DASSGN(iochan);
  118.     if (status != SS$_NORMAL)
  119.         exit(status);
  120. }
  121.  
  122. /*
  123.  * Write a character to the display.
  124.  * On VMS, terminal output is buffered, and
  125.  * we just put the characters in the big array,
  126.  * after checking for overflow.
  127.  */
  128. ttputc(c)
  129. {
  130.     if (nobuf >= NOBUF)
  131.         ttflush();
  132.     obuf[nobuf++] = c;
  133. }
  134.  
  135. /*
  136.  * This function does the real work of
  137.  * flushing out buffered I/O on VMS. All
  138.  * we do is blast out the block with a write call. No status
  139.  * checking is done on the write, because there isn't anything
  140.  * clever that can be done, and because you will see the
  141.  * error as a messed up screen.
  142.  */
  143. ttflush()
  144. {
  145.     int    iosb[2];
  146.  
  147.     if (nobuf != 0) {
  148.         SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
  149.         iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
  150.         nobuf = 0;
  151.     }
  152. }
  153.  
  154. /*
  155.  * Read a character from the terminal,
  156.  * performing no editing and doing no echo at all.
  157.  * More complex in VMS that almost anyplace else,
  158.  * which figures.
  159.  */
  160. ttgetc()
  161. {
  162.     int    status;
  163.     int    iosb[2];
  164.     int    term[2];
  165.  
  166.     term[0] = 0;
  167.     term[1] = 0;
  168.     while (ibufi >= nibuf) {
  169.         ibufi   = 0;
  170.         status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
  171.              iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
  172.         if (status != SS$_NORMAL)
  173.             continue;
  174.         status = iosb[0] & 0xFFFF;
  175.         if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
  176.             continue;
  177.         nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  178.         if (nibuf == 0) {
  179.             status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
  180.                 iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
  181.             if (status != SS$_NORMAL)
  182.                 continue;
  183.             if ((iosb[0]&0xFFFF) != SS$_NORMAL)
  184.                 continue;
  185.             nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  186.         }
  187.     }
  188.     return (ibuf[ibufi++] & 0xFF);
  189. }
  190.  
  191. /*
  192.  * Internal check for new terminal size.
  193.  * Do this *before* setting terminal modes, so
  194.  * the size changes are kept when.
  195.  */
  196. ckttysize()
  197. {
  198.     int status, mode[3], iosb[2], wid, len;
  199.  
  200.     status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
  201.               mode, sizeof(mode), 0, 0, 0, 0);
  202.     if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  203.         panic("ckttsize: can't sense terminal modes!");
  204.  
  205.     /* save new page length */
  206.     len = (mode[1] >> 24) & 0xFF;
  207.     oldmode[1] = (oldmode[1] & 0x00FFFFFF) | (len << 24);
  208.     newmode[1] = (newmode[1] & 0x00FFFFFF) | (len << 24);
  209.  
  210.     /* save new page width */
  211.     wid = (mode[0] >> 16) & 0xFF;
  212.     oldmode[0] = (oldmode[0] & 0x0000FFFF) | (wid << 16);
  213.     newmode[0] = (newmode[0] & 0x0000FFFF) | (wid << 16);
  214. }
  215.  
  216. /*
  217.  * Tell Emacs how big the terminal is now,
  218.  * making sure the page size is in the range
  219.  * 1..NROW.
  220.  */
  221.  
  222. setttysize()
  223. {
  224.     nrow = (newmode[1]>>24) & 0xFF;        /* Length.        */
  225.     if (nrow > NROW)
  226.         nrow = NROW;
  227.  
  228.     ncol = (newmode[0]>>16) & 0xFFFF;    /* Width.        */
  229.     if (ncol > NCOL)
  230.         ncol = NCOL;
  231. }
  232.  
  233. /*
  234.  * Return the number of characters in the
  235.  * typeahead buffer.
  236.  */
  237.  
  238. typeahead()
  239. {
  240.     int    status, SYS$QIOW(), iosb[2], mode[2];
  241.  
  242.     status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE|IO$M_TYPEAHDCNT,
  243.             iosb, 0, 0, mode, sizeof(mode), 0, 0, 0, 0);
  244.     if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  245.         exit(status);
  246.     return (mode[0] & 0xFFFF);    /* # characters in typeahead buf */
  247. }
  248.  
  249. #ifndef    NO_DPROMPT
  250. /*
  251.  * Attempt to read for one character.  Return TRUE if the
  252.  * read times out after 2 seconds, return immediately with
  253.  * FALSE if the user enters something.
  254.  */
  255. ttwait()
  256. {
  257.     int    status;
  258.     int    iosb[2];
  259.     int    term[2];
  260.  
  261.     term[0] = 0;                /* no termination char for read */
  262.     term[1] = 0;
  263.     while (ibufi >= nibuf) {    /* anything in the buffer?    */
  264.         ibufi   = 0;        /* nope, read 1 char w/timeout    */
  265.         status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
  266.              iosb, 0, 0, ibuf, 1, 2, term, 0, 0);
  267.         if (status != SS$_NORMAL)
  268.             continue;        /* did read succeed ?         */
  269.         status = iosb[0] & 0xFFFF;    /* yes, get secondary status */
  270.         if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
  271.             continue;        /* try again if bad         */
  272.         nibuf = (iosb[0]>>16) + (iosb[1]>>16);/* store # chars read  */
  273.         if (status == SS$_TIMEOUT)
  274.             return (TRUE);        /* the read timed out         */
  275.     }
  276.     return (FALSE);                /* read did not time out     */
  277. }
  278. #endif
  279.  
  280. /*
  281.  * Just exit, as quickly as we can.
  282.  */
  283.  
  284. panic(s)
  285. char *s;
  286. {
  287.     fprintf(stderr,"panic: %s\n\n", s);
  288.     ttclose();        /* set the terminal back to sane state... */
  289.     exit(SS$_ABORT);    /* go away! */
  290. }
  291.